 package com.vibration.utils;

 /**
 * 各地图API坐标系统比较与转换; 
 * 
 * WGS84坐标系：即地球坐标系，国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系, 
 * 谷歌地图采用的是WGS84地理坐标系（中国范围除外）; 
 * 
 * GCJ02坐标系：即火星坐标系，是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。 
 * 
 * IOS地图（高德地图）、Google 地图、搜搜、阿里云、腾讯 使用 火星坐标系。
 * 
 * 谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系; 
 * 
 * BD09坐标系：即百度坐标系，GCJ02坐标系经加密后的坐标系; 
 * 
 */ 
public class MapGPSTranslateUtil {
	public static final double pi = 3.1415926535897932384626;
	public static final double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
	public static final double a = 6378245.0;
	public static final double ee = 0.00669342162296594323;


	public static double transformLat(double x, double y) {
		double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
				+ 0.2 * Math.sqrt(Math.abs(x));
		ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
		ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
		return ret;
	}

	public static double transformLon(double x, double y) {
		double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
				* Math.sqrt(Math.abs(x));
		ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
		ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
				* pi)) * 2.0 / 3.0;
		return ret;
	}

	public static double[] transform(double lat, double lon) {
		if (outOfChina(lat, lon)) {
			return new double[] { lat, lon };
		}
		double dLat = transformLat(lon - 105.0, lat - 35.0);
		double dLon = transformLon(lon - 105.0, lat - 35.0);
		double radLat = lat / 180.0 * pi;
		double magic = Math.sin(radLat);
		magic = 1 - ee * magic * magic;
		double sqrtMagic = Math.sqrt(magic);
		dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
		dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
		double mgLat = lat + dLat;
		double mgLon = lon + dLon;
		return new double[] { mgLat, mgLon };
	}

	public static boolean outOfChina(double lat, double lon) {
		if (lon < 72.004 || lon > 137.8347)
			return true;
		if (lat < 0.8293 || lat > 55.8271)
			return true;
		return false;
	}

	/**
	 * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
	 * 
	 * @param lat
	 * @param lon
	 * @return
	 */
	public static double[] gps84_To_Gcj02(double lat, double lon) {
		if (outOfChina(lat, lon)) {
			return new double[] { lat, lon };
		}
		double dLat = transformLat(lon - 105.0, lat - 35.0);
		double dLon = transformLon(lon - 105.0, lat - 35.0);
		double radLat = lat / 180.0 * pi;
		double magic = Math.sin(radLat);
		magic = 1 - ee * magic * magic;
		double sqrtMagic = Math.sqrt(magic);
		dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
		dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
		double mgLat = lat + dLat;
		double mgLon = lon + dLon;
		return new double[] { mgLat, mgLon };
	}

	/**
	 * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
	 * */
	public static double[] gcj02_To_Gps84(double lat, double lon) {
		double[] gps = transform(lat, lon);
		double lontitude = lon * 2 - gps[1];
		double latitude = lat * 2 - gps[0];
		return new double[] { latitude, lontitude };
	}

	/**
	 * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
	 * 
	 * @param lat
	 * @param lon
	 */
	public static double[] gcj02_To_Bd09(double lat, double lon) {
		double x = lon, y = lat;
		double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
		double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
		double tempLon = z * Math.cos(theta) + 0.0065;
		double tempLat = z * Math.sin(theta) + 0.006;
		double[] gps = { tempLat, tempLon };
		return gps;
	}


	/**
	 * * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 *
	 * 
	 * @param bd_lat
	 *            *
	 * @param bd_lon
	 *            *
	 * @return
	 */
	public static double[] bd09_To_Gcj02(double lat, double lon) {
		double x = lon - 0.0065, y = lat - 0.006;
		double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
		double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
		double tempLon = z * Math.cos(theta);
		double tempLat = z * Math.sin(theta);
		double[] gps = { tempLat, tempLon };
		return gps;
	}

	/**
	 * 将gps84转为bd09
	 * 
	 * @param lat 纬度
	 * @param lon 经度
	 * @return
	 */
	public static double[] gps84_To_bd09(double lat, double lon) {
		double[] gcj02 = gps84_To_Gcj02(lat, lon);
		double[] bd09 = gcj02_To_Bd09(gcj02[0], gcj02[1]);
		bd09[0] = retain6(bd09[0]);
		bd09[1] = retain6(bd09[1]);
		
		return bd09;
	}


	public static double[] bd09_To_gps84(double lat, double lon) {
		double[] gcj02 = bd09_To_Gcj02(lat, lon);
		double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
		// 保留小数点后六位
		gps84[0] = retain6(gps84[0]);
		gps84[1] = retain6(gps84[1]);
		return gps84;
	}

	/**
	 * 保留小数点后六位
	 * 
	 * @param num
	 * @return
	 */
	private static double retain6(double num) {
		String result = String.format("%.6f", num);
		return Double.valueOf(result);
	}

	 public static String[] L76_to_Gps (String lon,String lat){
		 String[] latLon = new String[2];
		 latLon[0] = String.valueOf(Double.parseDouble(lon.substring(0,3))+ Double.parseDouble(lon.substring(3))/60);
		 latLon[1] = String.valueOf(Double.parseDouble(lat.substring(0,2))+ Double.parseDouble(lat.substring(2))/60);
		 return latLon;
	 }
	 /**
	  * 度分秒转经纬度
	  *
	  * @param dms 116°25'7.85"
	  * @return 116.418847
	  */
	 public static double dfm2LatLng(double dms) {
		 if (dms+"" == null) return 0;
		 String dmsStr = dms+"";
		 try {
			 int d = 0;
			 int f = 0;
			 double m = 0.0;
			 if(dmsStr.indexOf(".")==6){
				 d = Integer.parseInt(dmsStr.substring(0,2));
				 f = Integer.parseInt(dmsStr.substring(2,4));
				 m = Double.parseDouble(dmsStr.substring(4));
			 }else if(dmsStr.indexOf(".")==7){
				 d = Integer.parseInt(dmsStr.substring(0,3));
				 f = Integer.parseInt(dmsStr.substring(3,5));
				 m = Double.parseDouble(dmsStr.substring(5));
			 }else{
				 return 0;
			 }
			 double fen = f + (m / 60);
			 double du = (fen / 60) + Math.abs(d);
			 if (d < 0) du = -du;
			 return Double.parseDouble(String.format("%.6f", du));
		 } catch (Exception e) {
			 e.printStackTrace();
		 }
		 return 0;
	 }
	 public static double df2d(String df){
		 if (df+"" == null) return 0;
		 try {
			 int d = 0;
			 double f = 0;
			 if(df.indexOf(".")==4){
				 d = Integer.parseInt(df.substring(0,2));
				 f = Double.parseDouble(df.substring(2));
			 }else if(df.indexOf(".")==5){
				 d = Integer.parseInt(df.substring(0,3));
				 f = Double.parseDouble(df.substring(3));
			 }else{
				 return 0;
			 }
			 double du = (f / 60) + Math.abs(d);
			 if (d < 0) du = -du;
			 return Double.parseDouble(String.format("%.6f", du));
		 } catch (Exception e) {
			 e.printStackTrace();
		 }
		 return 0;
	 }

	 public static double[] dfmTobd09(double lat,double lon){
		 Double l1 = dfm2LatLng(lat);
		 Double l2 = dfm2LatLng(lon);
		 return gps84_To_bd09(l1,l2);
	 }
	 public static String str2HexStr(String str) {
		 char[] chars = "0123456789ABCDEF".toCharArray();
		 StringBuilder sb = new StringBuilder("");
		 byte[] bs = str.getBytes();
		 int bit;
		 for (int i = 0; i < bs.length; i++) {
			 bit = (bs[i] & 0x0f0) >> 4;
			 sb.append(chars[bit]);
			 bit = bs[i] & 0x0f;
			 sb.append(chars[bit]);
			 // sb.append(' ');
		 }
		 return sb.toString().trim();
	 }
	 /**
	  * 16进制直接转换成为字符串(无需Unicode解码)
	  *
	  * @param hexStr
	  * @return
	  */
	 public static String hexStr2Str(String hexStr) {
		 String str = "0123456789ABCDEF";
		 char[] hexs = hexStr.toCharArray();
		 byte[] bytes = new byte[hexStr.length() / 2];
		 int n;
		 for (int i = 0; i < bytes.length; i++) {
			 n = str.indexOf(hexs[2 * i]) * 16;
			 n += str.indexOf(hexs[2 * i + 1]);
			 bytes[i] = (byte) (n & 0xff);
		 }
		 return new String(bytes);
	 }

	public static void main(String[] args) {
		double[] bb = dfmTobd09( 320507.696800  ,1185459.469000 );
		System.err.println(bb[0]+","+bb[1]);
		//wps-84 转百度坐标
		//3640.87878,N,11706.61683,E,
		double[] arr1 = gps84_To_bd09(36.681313, 117.1102805);
		System.out.println("WPS84 转 百度坐标 =" + arr1[1] + "," + arr1[0]);
		double[] arr2 = gps84_To_Gcj02(36.681265, 117.110111);
		System.out.println("WPS84 转高德坐标=" + arr2[1] + "," + arr2[0]);
		System.out.println(str2HexStr("$GNGGA"));


		String str = "24474E4747412C3037353033392E3030302C333634302E38373837382C4E2C31313730362E36313638332C452C312C31392C302E372C3132362E322C4D2C302E302C4D2C2C2A3730";
		String str1 = hexStr2Str(str);
		String[] strs = str1.split(",");
		if(strs.length>5){
			String lat = strs[2];
			String lon = strs[4];
			Double l1 = df2d(lat);
			Double l2 = df2d(lon);
			double[] arr3 = gps84_To_bd09(l1,l2);
			System.out.println("WPS84 转 百度坐标 =" + arr3[1] + "," + arr3[0]);
			Long a = (long)Math.round(10.00);
			System.out.println(a);
		}
		String ret = "01032800000842000008950000070E000007FB00000984000007E7000009C60000083C00000813000008B840A4";
		String temp5 = ret.substring(6,14);
		System.out.println(Integer.parseInt(temp5,16)/100.00);
		String temp10 = ret.substring(14,22);
		System.out.println(Integer.parseInt(temp10,16)/100.00);
		String temp15 = ret.substring(22,30);
		System.out.println(Integer.parseInt(temp15,16)/100.00);
		String temp20 = ret.substring(30,38);
		System.out.println(Integer.parseInt(temp20,16)/100.00);
		String temp25 = ret.substring(38,46);
		System.out.println(Integer.parseInt(temp25,16)/100.00);
		String temp30 = ret.substring(46,54);
		System.out.println(Integer.parseInt(temp30,16)/100.00);
		String temp35 = ret.substring(54,62);
		System.out.println(Integer.parseInt(temp35,16)/100.00);
		String temp40 = ret.substring(62,70);
		System.out.println(Integer.parseInt(temp40,16)/100.00);
		String temp45 = ret.substring(70,78);
		System.out.println(Integer.parseInt(temp45,16)/100.00);
		String temp50 = ret.substring(78,86);
		System.out.println(Integer.parseInt(temp50,16)/100.00);

	}
}
